package com.abapi.pay.handler;

import cn.hutool.json.JSONUtil;
import com.abapi.pay.AbapiPayProperties;
import com.abapi.pay.SpringContext;
import com.abapi.pay.core.annotation.AbapiPayCallback;
import com.abapi.pay.core.biz.Decode;
import com.abapi.pay.core.biz.Encode;
import com.abapi.pay.client.PayTcpClient;
import com.abapi.pay.core.constans.MessageType;
import com.abapi.pay.core.dto.AliBizDTO;
import com.abapi.pay.core.dto.MessageDTO;
import com.abapi.pay.core.dto.SuccessDTO;
import com.abapi.pay.core.dto.WxBizDTO;
import com.abapi.pay.service.AbstractEndpointService;
import com.abapi.pay.service.RegisterService;
import com.alibaba.fastjson.JSON;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @Author ldx
 * @Date 2019/10/30 15:33
 * @Description
 * @Version 1.0.0
 */
@Component
public class ClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    Logger logger = LoggerFactory.getLogger(getClass());

    private Channel channel;

    final TimerTask task = new TimerTask() {
        @Override
        public void run() {
            MessageDTO dto = new MessageDTO();
            dto.setType(MessageType.PING);
            logger.debug("heart beat");
            ByteBuf buf = channel.alloc().buffer();
            buf.writeBytes(Encode.encode(dto));
            channel.writeAndFlush(buf);
        }
    };
    Timer timer = new Timer();
    // 定义开始等待时间  --- 等待 1 秒
    long delay = 3000;
    // 定义每次执行的间隔时间
    long intevalPeriod = 3 * 1000;

    private final PayTcpClient payTcpClient;

    private final AbapiPayProperties abapiPayProperties;

    private static String captureName(String s) {
        if(Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    public ClientHandler(PayTcpClient payTcpClient,AbapiPayProperties abapiPayProperties) {
        this.payTcpClient = payTcpClient;
        this.abapiPayProperties = abapiPayProperties;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext context, ByteBuf byteBuf) throws Exception {
        try {
            if(byteBuf.readableBytes()<=0){
                return;
            }
            byte[] bs = new byte[byteBuf.readableBytes()];
            byteBuf.readBytes(bs);
            MessageDTO decode = Decode.decode(bs);


            AbstractEndpointService instance = HandlerEndpointFactory.handlerClassMap.get(decode.getType());
            if(instance != null){
                instance.handler(context,decode);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        // IdleStateHandler 所产生的 IdleStateEvent 的处理逻辑.
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            switch (e.state()) {
                case READER_IDLE:
                    handleReaderIdle(ctx);
                    break;
                case WRITER_IDLE:
                    handleWriterIdle(ctx);
                    break;
                case ALL_IDLE:
                    handleAllIdle(ctx);
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        System.out.println("---" + ctx.channel().remoteAddress() + " is active 连接---");
        this.channel = ctx.channel();

        // 注册当前地址,业务名，多业务名
        new RegisterService(abapiPayProperties).register(ctx);

        // 开启心跳机制
        timer.scheduleAtFixedRate(task, delay, intevalPeriod);


    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.err.println("---" + ctx.channel().remoteAddress() + " is inactive 断开连接---");
        timer.cancel();
        this.channel = null;
        payTcpClient.doConnect();
    }

    protected void handleReaderIdle(ChannelHandlerContext ctx) {
        System.err.println("---READER_IDLE---");
        ctx.close();
    }

    protected void handleWriterIdle(ChannelHandlerContext ctx) {
        System.err.println("---WRITER_IDLE---");
        ctx.close();
    }

    protected void handleAllIdle(ChannelHandlerContext ctx) {
        System.err.println("---ALL_IDLE---");
        ctx.close();
    }

}
